/**
 * 
 */
package jnzb.control.loader;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Iterator;

import javax.swing.JOptionPane;

import jnzb.control.Configuration;
import jnzb.control.events.InfoEventProcessor;
import jnzb.model.binding.CorruptProgressException;
import jnzb.model.binding.NZBBinder;
import jnzb.model.nzb.NZB;
import nanoxml.XMLParseException;

/**
 * Responsible for NZB file related operations
 * 
 * @author AA1
 */
public class NZBStorage {

	private static Configuration config = Configuration.getInstance();

	/**
	 * All static methods
	 */
	private NZBStorage() {

	}

	/**
	 * Loads an NZB either from the NZB file or from the progress file if it
	 * exists
	 * 
	 * @param file
	 * @return
	 * @throws IOException
	 * @throws XMLParseException
	 */
	public static NZB loadNZB(File file, InfoEventProcessor eventProcessor)
			throws XMLParseException, IOException {
		return loadNZB(file, eventProcessor, true);
	}

	/**
	 * Loads an NZB either from the NZB file or from the progress file if it
	 * exists
	 * 
	 * @param file
	 * @return
	 * @throws IOException
	 * @throws XMLParseException
	 */
	public static NZB loadNZB(File file, InfoEventProcessor eventProcessor,
			boolean offerContinue) throws XMLParseException, IOException {

		NZB nzb = null;
		if (progressFileExists(file.getName()) && offerContinue) {
			// Default to always continue unles config says we should ask
			int response = JOptionPane.YES_OPTION;
			if (!Configuration.getInstance().getAlwaysContinue()) {
				response = JOptionPane.showConfirmDialog(null,
						"Do you wish to continue with the previous download?",
						"Previous Download Found", JOptionPane.YES_NO_OPTION,
						JOptionPane.QUESTION_MESSAGE);
			}
			if (response == JOptionPane.YES_OPTION) {
				// Load from progress file
				try {
					nzb = NZBBinder.loadProgressFile(file.getName());
				} catch (CorruptProgressException p) {
					// Couldnt load from progress file so load from nzb
					eventProcessor.error(p.getMessage());
					deleteProgressFile(file.getName());
					nzb = NZBBinder.loadFromFile(file.getPath());
				}
			} else {
				// Load NZB
				nzb = NZBBinder.loadFromFile(file.getPath());
				// Remove old progress file as NO was picked
				deleteProgressFile(file.getName());
			}
		} else {
			nzb = NZBBinder.loadFromFile(file.getPath());
			applyConfigFilters(nzb);
		}
		return nzb;
	}

	/**
	 * For each file in the NZB apply the filters in the config (ignore
	 * samples/par2)
	 * 
	 * @param nzb
	 */
	private static void applyConfigFilters(NZB nzb) {
		// Check if we're applying any filters
		boolean ignorePar = config.ignoreParFiles();
		boolean ignoreSample = config.ignoreSampleFiles();

		if (ignorePar || ignoreSample) {
			Iterator<jnzb.model.nzb.File> files = nzb.getFiles().iterator();

			jnzb.model.nzb.File file;
			String subject;
			while (files.hasNext()) {
				file = files.next();
				subject = file.getSubject();
				if (subject != null && subject.trim().length() > 0) {
					if (ignorePar) {
						// We never ignore the .par2 file, just the volume files
						if (subject.toLowerCase().indexOf("vol") > -1
								&& subject.toLowerCase().indexOf(".par2") > -1) {
							// Subject contains vol & par2
							file.setIgnore(true);
						}
					}
					if (ignoreSample) {
						// Only ignore sample if the main NZB filename doesnt
						// contain the word sample!
						if (nzb.getFilename().toLowerCase().indexOf("sample") == -1) {
							// If this filename contains the word sample, ignore
							if (subject.toLowerCase().indexOf("sample") > -1) {
								file.setIgnore(true);
							}
						}
					}
				}
			}
		}
	}

	/**
	 * Persist the NZB to the NZB folder to indicate progress.<br>
	 * Saves to <code>[nzb filename].progress</code>
	 * 
	 * @param nzb
	 * @throws IOException
	 */
	public static void saveProgress(NZB nzb) throws IOException {
		String name = nzb.getFilename();
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(Configuration.getInstance().getNZBPath(
					name)
					+ name + ".progress");
			BufferedOutputStream bos = new BufferedOutputStream(fos);
			ObjectOutputStream oos = new ObjectOutputStream(bos);

			// Serialise the file
			oos.writeObject(nzb);

			oos.close();
			bos.close();
			fos.close();
		} finally {
			if (fos != null) {
				fos.close();
			}
		}
	}

	/**
	 * Checks if there is a progress file for the NZB
	 * 
	 * @param name
	 * @return
	 */
	private static boolean progressFileExists(String name) {
		File p = new File(config.getNZBPath(name) + name + ".progress");
		return p.exists();
	}

	/**
	 * Deletes the progress file for the named nzb
	 * 
	 * @param name
	 *            - the name of the nzb
	 * @return true if deleted OK
	 */
	public static boolean deleteProgressFile(String name) {
		File p = new File(config.getNZBPath(name) + name + ".progress");
		return p.delete();
	}

	/**
	 * Removes the segment directory
	 * 
	 * @param nzbFilename
	 */
	public static void deleteSegmentsDirectory(String nzbFilename) {
		File s = new File(config.getSegmentPath(nzbFilename));
		s.delete();
	}

}
